/*
 * Copyright (C) 2016
 *
 * Brick Yang <printfxxx@163.com>
 *
 * This program is free software. You can redistribute it and/or
 * modify it as you like.
 */

/**
 * @file	qman.h
 * @brief	Header file for qman driver
 */

#ifndef _QMAN_H_
#define _QMAN_H_

#include <linux/types.h>
#include <linux/device.h>

/* qman software portal descriptor structure */
struct qman_swp_desc {
	void *cena_bar;
	void *cinh_bar;
	size_t cena_size;
	size_t cinh_size;
	unsigned long flags;
	#define SWP_F_EST	0x01
	#define SWP_F_RE	0x02
	#define SWP_F_EQCR_VB	0x04
	#define SWP_F_DQRR_VB	0x08
	#define SWP_F_MR_VB	0x10
};

/* portal data structure */
struct qman_swp {
	const struct qman_swp_desc *desc;
	void __iomem *addr_cena;
	void __iomem *addr_cinh;

	/* Push dequeues */
	u32 sdq;

	/* CR */
	struct {
		u8 valid_bit;
	} cr;

	/* DQRR */
	struct {
		u8 pi, ci, fi;
		u8 pi_ci_mask;
		u8 valid_bit;
	} dqrr;

	/* EQCR */
	struct {
		u8 pi, ci, fi;
		u8 pi_ci_mask;
		u8 valid_bit;
	} eqcr;

	/* MR */
	struct {
		u8 pi, ci, fi;
		u8 pi_ci_mask;
		u8 valid_bit;
	} mr;
};

static inline void qman_swp_cmd_zero(void __iomem *p)
{
	u32 *w = p;

	w[0] = 0;
	w[1] = 0;
	w[2] = 0;
	w[3] = 0;
	w[4] = 0;
	w[5] = 0;
	w[6] = 0;
	w[7] = 0;
	w[8] = 0;
	w[9] = 0;
	w[10] = 0;
	w[11] = 0;
	w[12] = 0;
	w[13] = 0;
	w[14] = 0;
	w[15] = 0;
}

struct qman_swp *qman_swp_init(const struct qman_swp_desc *d);
void qman_swp_finish(struct qman_swp *s);
void __iomem *qman_swp_cr_next(struct qman_swp *s, u8 *cmd_verb);
const void __iomem *qman_swp_rr_next(struct qman_swp *s, u8 cmd_verb);
void __iomem *qman_swp_eqcr_next(struct qman_swp *s, u8 *cmd_verb);
const void __iomem *qman_swp_dqrr_next(struct qman_swp *s);
const void __iomem *qman_swp_mr_next(struct qman_swp *s);
void qman_swp_cr_submit(struct qman_swp *s, void __iomem *p, u8 cmd_verb);
int qman_swp_eqcr_submit(struct qman_swp *s, void __iomem *p, u8 cmd_verb, bool flush);
int qman_swp_dqrr_consume(struct qman_swp *s, const void __iomem *p, bool flush);
int qman_swp_mr_consume(struct qman_swp *s, const void __iomem *p, bool flush);
u8 qman_swp_push_chid_to_idx(u16 chid);
void qman_swp_push_get(struct qman_swp *s, u8 idx, bool *en);
void qman_swp_push_set(struct qman_swp *s, u8 idx, bool en);

#endif	/* _QMAN_H_ */
